package com.sk.client.level1.autoDynamicProxy;


import com.sk.common.level1.ObjectUtil;
import com.sk.client.level1.ClientSocket;
import com.sk.common.level1.MethodParamRpc;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.io.ClassPathResource;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Properties;

/**
 * 动态代理，需要注意的是，这里用到的是JDK自带的动态代理，代理对象只能是接口，不能是类
 * @author 孙文斌
 */

@Data
@Slf4j
public class ServiceProxy<T> implements InvocationHandler {

    private Class<T> interfaceType;
    private ClientSocket clientSocket;

    private final  String RPC_SERVER_SOCKET_IP = "rpc.server.socket.ip";
    private final  String RPC_SERVER_SOCKET_PORT = "rpc.server.socket.port";

    public ServiceProxy(Class<T> intefaceType) {
        this.interfaceType = interfaceType;
        this.clientSocket = initClientSocket();
    }


    private ClientSocket initClientSocket() {
        String ip = null;
        Integer port= null;
        ClientSocket clientSocket = null;
        try {
            YamlPropertiesFactoryBean yamlMapFactoryBean = new YamlPropertiesFactoryBean(); //可以加载多个yml文件
            yamlMapFactoryBean.setResources(new ClassPathResource("application.yml"));
            Properties properties = yamlMapFactoryBean.getObject(); //获取yml里的参数
            ip = properties.getProperty(RPC_SERVER_SOCKET_IP);
            port = Integer.valueOf(properties.getProperty(RPC_SERVER_SOCKET_PORT));
            clientSocket = new ClientSocket(ip,port);
        } catch (Exception e) {
            log.error("init clientSocket fail,"+e);
        }
        return ObjectUtil.checkNotNull(clientSocket,"clientSocket is null");
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (Object.class.equals(method.getDeclaringClass())) {
            return method.invoke(this,args);
        }
        MethodParamRpc methodParam = new MethodParamRpc();
        methodParam.setClassName(method.getDeclaringClass().getName());
        methodParam.setMethodName(method.getName());
        methodParam.setArguments(args);
        methodParam.setParameterTypes(method.getParameterTypes());
        return clientSocket.invoke(methodParam);
    }
}